import { useState } from "react";

export { useQuickFilterFn, useQuickFilterWithPageFn, writeQuickFilterToUrlFn };

interface UserQuickFilterWithPageProps<V extends Record<string, any>> {
  key?: string;
  condition?: V | (() => V);
  pageSize?: number;
  pageNum?: number;
}

type QuickFilterWithPageValue<V> = {
  condition?: V;
  pageSize?: number;
  pageNum?: number;
};

function isFunctionValue<V>(v?: V | (() => V)): v is () => V {
  return typeof v == "function";
}

function useQuickFilterWithPageFn<V extends Record<string, any>>(
  props?: UserQuickFilterWithPageProps<V>
): [
  QuickFilterWithPageValue<V>,
  (params: QuickFilterWithPageValue<V>) => void
] {
  const {
    key = "_qf",
    condition: propsCondition,
    pageSize: propsPageSize,
    pageNum: propsPageNum,
  } = props || {};

  const [filter, setFilter] = useState<QuickFilterWithPageValue<V>>(() => {
    const { condition, pageSize, pageNum } = readQuickFilterFromUrl(key);
    const defaultState = isFunctionValue<V>(propsCondition)
      ? propsCondition()
      : propsCondition;
    const cond: V = Object.assign({}, defaultState, condition);
    return {
      condition: cond,
      pageNum: pageNum || propsPageNum,
      pageSize: pageSize || propsPageSize,
    };
  });

  const setHandler = (params: QuickFilterWithPageValue<V>) => {
    const nextFilter: QuickFilterWithPageValue<V> = Object.assign(
      {},
      filter,
      params
    );
    setFilter(nextFilter);
    if (key) writeQuickFilterToUrlFn(key, nextFilter);
  };

  return [filter, setHandler];
}

function useQuickFilterFn<V extends Record<string, any>>(
  defaultFilter?: V | (() => V),
  key?: string
): [V, (filter: V) => void] {
  const K = key ?? "_uqf";
  const [filter, setFilter] = useState<V>(() => {
    const { condition } = readQuickFilterFromUrl(key);
    const defaultState = isFunctionValue<V>(defaultFilter)
      ? defaultFilter()
      : defaultFilter;
    const cond: V = Object.assign({}, defaultState, condition);
    return cond;
  });

  const setHandler = (params: V) => {
    const condition: V = Object.assign({}, filter, params);
    setFilter(condition);
    if (K) writeQuickFilterToUrlFn(K, { condition });
  };

  return [filter, setHandler];
}

function writeQuickFilterToUrlFn(
  key: string,
  filter: QuickFilterWithPageValue<any>
) {
  const href = location.href.split("?")[0];
  const search = new URLSearchParams(location.search);
  search.set(key, JSON.stringify(filter.condition));
  search.set(
    getPageKey(key),
    JSON.stringify({ num: filter.pageNum, size: filter.pageSize })
  );
  const newUrl = href + "?" + search.toString();
  history.replaceState("", "", newUrl);
}

function readQuickFilterFromUrl(key?: string): {
  condition: Record<string, any>;
  pageSize?: number;
  pageNum?: number;
} {
  if (!key) return { condition: {} };

  const params = new URLSearchParams(window.location.search);
  const cond = params.get(key),
    page = params.get(getPageKey(key));
  let condition = {},
    pageSize,
    pageNum;

  try {
    condition = JSON.parse(cond || "{}");
  } catch (e) {
    console.error("useQuickFilter 解析 url 条件参数错误", e);
  }

  try {
    const p = JSON.parse(page || "{}");
    pageSize = p.size;
    pageNum = p.num;
  } catch (e) {
    console.error("useQuickFilter 解析 url 分页参数错误", e);
  }

  return {
    condition,
    pageNum,
    pageSize,
  };
}

function getPageKey(key: string) {
  return key + "_page";
}
